<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><link rel="stylesheet" type="text/css" href="style.css" /><script type="text/javascript" src="highlight.js"></script></head><body><pre><span class="hs-pragma">{-# LANGUAGE Trustworthy #-}</span><span>
</span><span id="line-2"></span><span>
</span><span id="line-3"></span><span class="hs-comment">-----------------------------------------------------------------------------</span><span>
</span><span id="line-4"></span><span class="hs-comment">-- |</span><span>
</span><span id="line-5"></span><span class="hs-comment">-- Module      :  System.Mem.Weak</span><span>
</span><span id="line-6"></span><span class="hs-comment">-- Copyright   :  (c) The University of Glasgow 2001</span><span>
</span><span id="line-7"></span><span class="hs-comment">-- License     :  BSD-style (see the file libraries/base/LICENSE)</span><span>
</span><span id="line-8"></span><span class="hs-comment">--</span><span>
</span><span id="line-9"></span><span class="hs-comment">-- Maintainer  :  libraries@haskell.org</span><span>
</span><span id="line-10"></span><span class="hs-comment">-- Stability   :  experimental</span><span>
</span><span id="line-11"></span><span class="hs-comment">-- Portability :  non-portable</span><span>
</span><span id="line-12"></span><span class="hs-comment">--</span><span>
</span><span id="line-13"></span><span class="hs-comment">-- In general terms, a weak pointer is a reference to an object that is</span><span>
</span><span id="line-14"></span><span class="hs-comment">-- not followed by the garbage collector - that is, the existence of a</span><span>
</span><span id="line-15"></span><span class="hs-comment">-- weak pointer to an object has no effect on the lifetime of that</span><span>
</span><span id="line-16"></span><span class="hs-comment">-- object.  A weak pointer can be de-referenced to find out</span><span>
</span><span id="line-17"></span><span class="hs-comment">-- whether the object it refers to is still alive or not, and if so</span><span>
</span><span id="line-18"></span><span class="hs-comment">-- to return the object itself.</span><span>
</span><span id="line-19"></span><span class="hs-comment">--</span><span>
</span><span id="line-20"></span><span class="hs-comment">-- Weak pointers are particularly useful for caches and memo tables.</span><span>
</span><span id="line-21"></span><span class="hs-comment">-- To build a memo table, you build a data structure</span><span>
</span><span id="line-22"></span><span class="hs-comment">-- mapping from the function argument (the key) to its result (the</span><span>
</span><span id="line-23"></span><span class="hs-comment">-- value).  When you apply the function to a new argument you first</span><span>
</span><span id="line-24"></span><span class="hs-comment">-- check whether the key\/value pair is already in the memo table.</span><span>
</span><span id="line-25"></span><span class="hs-comment">-- The key point is that the memo table itself should not keep the</span><span>
</span><span id="line-26"></span><span class="hs-comment">-- key and value alive.  So the table should contain a weak pointer</span><span>
</span><span id="line-27"></span><span class="hs-comment">-- to the key, not an ordinary pointer.  The pointer to the value must</span><span>
</span><span id="line-28"></span><span class="hs-comment">-- not be weak, because the only reference to the value might indeed be</span><span>
</span><span id="line-29"></span><span class="hs-comment">-- from the memo table.</span><span>
</span><span id="line-30"></span><span class="hs-comment">--</span><span>
</span><span id="line-31"></span><span class="hs-comment">-- So it looks as if the memo table will keep all its values</span><span>
</span><span id="line-32"></span><span class="hs-comment">-- alive for ever.  One way to solve this is to purge the table</span><span>
</span><span id="line-33"></span><span class="hs-comment">-- occasionally, by deleting entries whose keys have died.</span><span>
</span><span id="line-34"></span><span class="hs-comment">--</span><span>
</span><span id="line-35"></span><span class="hs-comment">-- The weak pointers in this library</span><span>
</span><span id="line-36"></span><span class="hs-comment">-- support another approach, called /finalization/.</span><span>
</span><span id="line-37"></span><span class="hs-comment">-- When the key referred to by a weak pointer dies, the storage manager</span><span>
</span><span id="line-38"></span><span class="hs-comment">-- arranges to run a programmer-specified finalizer.  In the case of memo</span><span>
</span><span id="line-39"></span><span class="hs-comment">-- tables, for example, the finalizer could remove the key\/value pair</span><span>
</span><span id="line-40"></span><span class="hs-comment">-- from the memo table.</span><span>
</span><span id="line-41"></span><span class="hs-comment">--</span><span>
</span><span id="line-42"></span><span class="hs-comment">-- Another difficulty with the memo table is that the value of a</span><span>
</span><span id="line-43"></span><span class="hs-comment">-- key\/value pair might itself contain a pointer to the key.</span><span>
</span><span id="line-44"></span><span class="hs-comment">-- So the memo table keeps the value alive, which keeps the key alive,</span><span>
</span><span id="line-45"></span><span class="hs-comment">-- even though there may be no other references to the key so both should</span><span>
</span><span id="line-46"></span><span class="hs-comment">-- die.  The weak pointers in this library provide a slight</span><span>
</span><span id="line-47"></span><span class="hs-comment">-- generalisation of the basic weak-pointer idea, in which each</span><span>
</span><span id="line-48"></span><span class="hs-comment">-- weak pointer actually contains both a key and a value.</span><span>
</span><span id="line-49"></span><span class="hs-comment">--</span><span>
</span><span id="line-50"></span><span class="hs-comment">-----------------------------------------------------------------------------</span><span>
</span><span id="line-51"></span><span>
</span><span id="line-52"></span><span class="hs-keyword">module</span><span> </span><span class="hs-identifier">System.Mem.Weak</span><span> </span><span class="hs-special">(</span><span>
</span><span id="line-53"></span><span>        </span><span class="annot"><span class="hs-comment">-- * The @Weak@ type</span></span><span>
</span><span id="line-54"></span><span>        </span><span class="annot"><a href="GHC.Weak.html#Weak"><span class="hs-identifier">Weak</span></a></span><span class="hs-special">,</span><span>                   </span><span class="hs-comment">-- abstract</span><span>
</span><span id="line-55"></span><span>
</span><span id="line-56"></span><span>        </span><span class="annot"><span class="hs-comment">-- * The general interface</span></span><span>
</span><span id="line-57"></span><span>        </span><span class="annot"><a href="GHC.Weak.html#mkWeak"><span class="hs-identifier">mkWeak</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-58"></span><span>        </span><span class="annot"><a href="GHC.Weak.html#deRefWeak"><span class="hs-identifier">deRefWeak</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-59"></span><span>        </span><span class="annot"><a href="GHC.Weak.html#finalize"><span class="hs-identifier">finalize</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-60"></span><span>
</span><span id="line-61"></span><span>        </span><span class="annot"><span class="hs-comment">-- * Specialised versions</span></span><span>
</span><span id="line-62"></span><span>        </span><span class="annot"><a href="System.Mem.Weak.html#mkWeakPtr"><span class="hs-identifier">mkWeakPtr</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-63"></span><span>        </span><span class="annot"><a href="System.Mem.Weak.html#addFinalizer"><span class="hs-identifier">addFinalizer</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-64"></span><span>        </span><span class="annot"><a href="System.Mem.Weak.html#mkWeakPair"><span class="hs-identifier">mkWeakPair</span></a></span><span class="hs-special">,</span><span>
</span><span id="line-65"></span><span>        </span><span class="hs-comment">-- replaceFinaliser</span><span>
</span><span id="line-66"></span><span>
</span><span id="line-67"></span><span>        </span><span class="annot"><span class="hs-comment">-- * A precise semantics</span></span><span>
</span><span id="line-68"></span><span>
</span><span id="line-69"></span><span>        </span><span class="annot"><span class="hs-comment">-- $precise</span></span><span>
</span><span id="line-70"></span><span>
</span><span id="line-71"></span><span>        </span><span class="annot"><span class="hs-comment">-- * Implementation notes</span></span><span>
</span><span id="line-72"></span><span>
</span><span id="line-73"></span><span>        </span><span class="annot"><span class="hs-comment">-- $notes</span></span><span>
</span><span id="line-74"></span><span>   </span><span class="hs-special">)</span><span> </span><span class="hs-keyword">where</span><span>
</span><span id="line-75"></span><span>
</span><span id="line-76"></span><span class="hs-keyword">import</span><span> </span><span class="annot"><a href="GHC.Weak.html"><span class="hs-identifier">GHC.Weak</span></a></span><span>
</span><span id="line-77"></span><span>
</span><span id="line-78"></span><span class="hs-comment">-- | A specialised version of 'mkWeak', where the key and the value are</span><span>
</span><span id="line-79"></span><span class="hs-comment">-- the same object:</span><span>
</span><span id="line-80"></span><span class="hs-comment">--</span><span>
</span><span id="line-81"></span><span class="hs-comment">-- &gt; mkWeakPtr key finalizer = mkWeak key key finalizer</span><span>
</span><span id="line-82"></span><span class="hs-comment">--</span><span>
</span><span id="line-83"></span><span id="local-6989586621679563848"><span class="annot"><a href="System.Mem.Weak.html#mkWeakPtr"><span class="hs-identifier hs-type">mkWeakPtr</span></a></span><span> </span><span class="hs-glyph">::</span><span> </span><span class="annot"><a href="#local-6989586621679563848"><span class="hs-identifier hs-type">k</span></a></span><span> </span><span class="hs-glyph">-&gt;</span><span> </span><span class="annot"><a href="GHC.Maybe.html#Maybe"><span class="hs-identifier hs-type">Maybe</span></a></span><span> </span><span class="hs-special">(</span><span class="annot"><a href="../../ghc-prim/src/GHC.Types.html#IO"><span class="hs-identifier hs-type">IO</span></a></span><span> </span><span class="hs-special">(</span><span class="hs-special">)</span><span class="hs-special">)</span><span> </span><span class="hs-glyph">-&gt;</span><span> </span><span class="annot"><a href="../../ghc-prim/src/GHC.Types.html#IO"><span class="hs-identifier hs-type">IO</span></a></span><span> </span><span class="hs-special">(</span><span class="annot"><a href="GHC.Weak.html#Weak"><span class="hs-identifier hs-type">Weak</span></a></span><span> </span><span class="annot"><a href="#local-6989586621679563848"><span class="hs-identifier hs-type">k</span></a></span><span class="hs-special">)</span></span><span>
</span><span id="line-84"></span><span id="mkWeakPtr"><span class="annot"><span class="annottext">mkWeakPtr :: forall k. k -&gt; Maybe (IO ()) -&gt; IO (Weak k)
</span><a href="System.Mem.Weak.html#mkWeakPtr"><span class="hs-identifier hs-var hs-var">mkWeakPtr</span></a></span></span><span> </span><span id="local-6989586621679563828"><span class="annot"><span class="annottext">k
</span><a href="#local-6989586621679563828"><span class="hs-identifier hs-var">key</span></a></span></span><span> </span><span id="local-6989586621679563827"><span class="annot"><span class="annottext">Maybe (IO ())
</span><a href="#local-6989586621679563827"><span class="hs-identifier hs-var">finalizer</span></a></span></span><span> </span><span class="hs-glyph">=</span><span> </span><span class="annot"><span class="annottext">k -&gt; k -&gt; Maybe (IO ()) -&gt; IO (Weak k)
forall k v. k -&gt; v -&gt; Maybe (IO ()) -&gt; IO (Weak v)
</span><a href="GHC.Weak.html#mkWeak"><span class="hs-identifier hs-var">mkWeak</span></a></span><span> </span><span class="annot"><span class="annottext">k
</span><a href="#local-6989586621679563828"><span class="hs-identifier hs-var">key</span></a></span><span> </span><span class="annot"><span class="annottext">k
</span><a href="#local-6989586621679563828"><span class="hs-identifier hs-var">key</span></a></span><span> </span><span class="annot"><span class="annottext">Maybe (IO ())
</span><a href="#local-6989586621679563827"><span class="hs-identifier hs-var">finalizer</span></a></span><span>
</span><span id="line-85"></span><span>
</span><span id="line-86"></span><span class="hs-comment">{-|
  A specialised version of 'mkWeakPtr', where the 'Weak' object
  returned is simply thrown away (however the finalizer will be
  remembered by the garbage collector, and will still be run
  when the key becomes unreachable).

  Note: adding a finalizer to a 'Foreign.ForeignPtr.ForeignPtr' using
  'addFinalizer' won't work; use the specialised version
  'Foreign.ForeignPtr.addForeignPtrFinalizer' instead.  For discussion
  see the 'Weak' type.
.
-}</span><span>
</span><span id="line-98"></span><span id="local-6989586621679563843"><span class="annot"><a href="System.Mem.Weak.html#addFinalizer"><span class="hs-identifier hs-type">addFinalizer</span></a></span><span> </span><span class="hs-glyph">::</span><span> </span><span class="annot"><a href="#local-6989586621679563843"><span class="hs-identifier hs-type">key</span></a></span><span> </span><span class="hs-glyph">-&gt;</span><span> </span><span class="annot"><a href="../../ghc-prim/src/GHC.Types.html#IO"><span class="hs-identifier hs-type">IO</span></a></span><span> </span><span class="hs-special">(</span><span class="hs-special">)</span><span> </span><span class="hs-glyph">-&gt;</span><span> </span><span class="annot"><a href="../../ghc-prim/src/GHC.Types.html#IO"><span class="hs-identifier hs-type">IO</span></a></span><span> </span><span class="hs-special">(</span><span class="hs-special">)</span></span><span>
</span><span id="line-99"></span><span id="addFinalizer"><span class="annot"><span class="annottext">addFinalizer :: forall key. key -&gt; IO () -&gt; IO ()
</span><a href="System.Mem.Weak.html#addFinalizer"><span class="hs-identifier hs-var hs-var">addFinalizer</span></a></span></span><span> </span><span id="local-6989586621679563823"><span class="annot"><span class="annottext">key
</span><a href="#local-6989586621679563823"><span class="hs-identifier hs-var">key</span></a></span></span><span> </span><span id="local-6989586621679563822"><span class="annot"><span class="annottext">IO ()
</span><a href="#local-6989586621679563822"><span class="hs-identifier hs-var">finalizer</span></a></span></span><span> </span><span class="hs-glyph">=</span><span> </span><span class="hs-keyword">do</span><span>
</span><span id="line-100"></span><span>   </span><span class="annot"><span class="annottext">Weak key
</span><span class="hs-identifier">_</span></span><span> </span><span class="hs-glyph">&lt;-</span><span> </span><span class="annot"><span class="annottext">key -&gt; Maybe (IO ()) -&gt; IO (Weak key)
forall k. k -&gt; Maybe (IO ()) -&gt; IO (Weak k)
</span><a href="System.Mem.Weak.html#mkWeakPtr"><span class="hs-identifier hs-var">mkWeakPtr</span></a></span><span> </span><span class="annot"><span class="annottext">key
</span><a href="#local-6989586621679563823"><span class="hs-identifier hs-var">key</span></a></span><span> </span><span class="hs-special">(</span><span class="annot"><span class="annottext">IO () -&gt; Maybe (IO ())
forall a. a -&gt; Maybe a
</span><a href="GHC.Maybe.html#Just"><span class="hs-identifier hs-var">Just</span></a></span><span> </span><span class="annot"><span class="annottext">IO ()
</span><a href="#local-6989586621679563822"><span class="hs-identifier hs-var">finalizer</span></a></span><span class="hs-special">)</span><span> </span><span class="hs-comment">-- throw it away</span><span>
</span><span id="line-101"></span><span>   </span><span class="annot"><span class="annottext">() -&gt; IO ()
forall (m :: * -&gt; *) a. Monad m =&gt; a -&gt; m a
</span><a href="GHC.Base.html#return"><span class="hs-identifier hs-var">return</span></a></span><span> </span><span class="hs-special">(</span><span class="hs-special">)</span><span>
</span><span id="line-102"></span><span>
</span><span id="line-103"></span><span class="hs-comment">-- | A specialised version of 'mkWeak' where the value is actually a pair</span><span>
</span><span id="line-104"></span><span class="hs-comment">-- of the key and value passed to 'mkWeakPair':</span><span>
</span><span id="line-105"></span><span class="hs-comment">--</span><span>
</span><span id="line-106"></span><span class="hs-comment">-- &gt; mkWeakPair key val finalizer = mkWeak key (key,val) finalizer</span><span>
</span><span id="line-107"></span><span class="hs-comment">--</span><span>
</span><span id="line-108"></span><span class="hs-comment">-- The advantage of this is that the key can be retrieved by 'deRefWeak'</span><span>
</span><span id="line-109"></span><span class="hs-comment">-- in addition to the value.</span><span>
</span><span id="line-110"></span><span id="local-6989586621679563837"><span id="local-6989586621679563838"><span class="annot"><a href="System.Mem.Weak.html#mkWeakPair"><span class="hs-identifier hs-type">mkWeakPair</span></a></span><span> </span><span class="hs-glyph">::</span><span> </span><span class="annot"><a href="#local-6989586621679563838"><span class="hs-identifier hs-type">k</span></a></span><span> </span><span class="hs-glyph">-&gt;</span><span> </span><span class="annot"><a href="#local-6989586621679563837"><span class="hs-identifier hs-type">v</span></a></span><span> </span><span class="hs-glyph">-&gt;</span><span> </span><span class="annot"><a href="GHC.Maybe.html#Maybe"><span class="hs-identifier hs-type">Maybe</span></a></span><span> </span><span class="hs-special">(</span><span class="annot"><a href="../../ghc-prim/src/GHC.Types.html#IO"><span class="hs-identifier hs-type">IO</span></a></span><span> </span><span class="hs-special">(</span><span class="hs-special">)</span><span class="hs-special">)</span><span> </span><span class="hs-glyph">-&gt;</span><span> </span><span class="annot"><a href="../../ghc-prim/src/GHC.Types.html#IO"><span class="hs-identifier hs-type">IO</span></a></span><span> </span><span class="hs-special">(</span><span class="annot"><a href="GHC.Weak.html#Weak"><span class="hs-identifier hs-type">Weak</span></a></span><span> </span><span class="hs-special">(</span><span class="annot"><a href="#local-6989586621679563838"><span class="hs-identifier hs-type">k</span></a></span><span class="hs-special">,</span><span class="annot"><a href="#local-6989586621679563837"><span class="hs-identifier hs-type">v</span></a></span><span class="hs-special">)</span><span class="hs-special">)</span></span></span><span>
</span><span id="line-111"></span><span id="mkWeakPair"><span class="annot"><span class="annottext">mkWeakPair :: forall k v. k -&gt; v -&gt; Maybe (IO ()) -&gt; IO (Weak (k, v))
</span><a href="System.Mem.Weak.html#mkWeakPair"><span class="hs-identifier hs-var hs-var">mkWeakPair</span></a></span></span><span> </span><span id="local-6989586621679563821"><span class="annot"><span class="annottext">k
</span><a href="#local-6989586621679563821"><span class="hs-identifier hs-var">key</span></a></span></span><span> </span><span id="local-6989586621679563820"><span class="annot"><span class="annottext">v
</span><a href="#local-6989586621679563820"><span class="hs-identifier hs-var">val</span></a></span></span><span> </span><span id="local-6989586621679563819"><span class="annot"><span class="annottext">Maybe (IO ())
</span><a href="#local-6989586621679563819"><span class="hs-identifier hs-var">finalizer</span></a></span></span><span> </span><span class="hs-glyph">=</span><span> </span><span class="annot"><span class="annottext">k -&gt; (k, v) -&gt; Maybe (IO ()) -&gt; IO (Weak (k, v))
forall k v. k -&gt; v -&gt; Maybe (IO ()) -&gt; IO (Weak v)
</span><a href="GHC.Weak.html#mkWeak"><span class="hs-identifier hs-var">mkWeak</span></a></span><span> </span><span class="annot"><span class="annottext">k
</span><a href="#local-6989586621679563821"><span class="hs-identifier hs-var">key</span></a></span><span> </span><span class="hs-special">(</span><span class="annot"><span class="annottext">k
</span><a href="#local-6989586621679563821"><span class="hs-identifier hs-var">key</span></a></span><span class="hs-special">,</span><span class="annot"><span class="annottext">v
</span><a href="#local-6989586621679563820"><span class="hs-identifier hs-var">val</span></a></span><span class="hs-special">)</span><span> </span><span class="annot"><span class="annottext">Maybe (IO ())
</span><a href="#local-6989586621679563819"><span class="hs-identifier hs-var">finalizer</span></a></span><span>
</span><span id="line-112"></span><span>
</span><span id="line-113"></span><span>
</span><span id="line-114"></span><span class="hs-comment">{- $precise

The above informal specification is fine for simple situations, but
matters can get complicated.  In particular, it needs to be clear
exactly when a key dies, so that any weak pointers that refer to it
can be finalized.  Suppose, for example, the value of one weak pointer
refers to the key of another...does that keep the key alive?

The behaviour is simply this:

 *  If a weak pointer (object) refers to an /unreachable/
    key, it may be finalized.

 *  Finalization means (a) arrange that subsequent calls
    to 'deRefWeak' return 'Nothing'; and (b) run the finalizer.

This behaviour depends on what it means for a key to be reachable.
Informally, something is reachable if it can be reached by following
ordinary pointers from the root set, but not following weak pointers.
We define reachability more precisely as follows.

A heap object is /reachable/ if:

 * It is a member of the /root set/.

 * It is directly pointed to by a reachable object, other than
   a weak pointer object.

 * It is a weak pointer object whose key is reachable.

 * It is the value or finalizer of a weak pointer object whose key is reachable.
-}</span><span>
</span><span id="line-146"></span><span>
</span><span id="line-147"></span><span class="hs-comment">{- $notes

A finalizer is not always called after its weak pointer\'s object becomes
unreachable. There are two situations that can cause this:

 * If the object becomes unreachable right before the program exits,
   then GC may not be performed. Finalizers run during GC, so finalizers
   associated with the object do not run if GC does not happen.

 * If a finalizer throws an exception, subsequent finalizers that had
   been queued to run after it do not get run. This behavior may change
   in a future release. See issue &lt;https://gitlab.haskell.org/ghc/ghc/issues/13167 13167&gt;
   on the issue tracker. Writing a finalizer that throws exceptions is
   discouraged.

Other than these two caveats, users can always expect that a finalizer
will be run after its weak pointer\'s object becomes unreachable. However,
the second caveat means that users need to trust that all of their
transitive dependencies do not throw exceptions in finalizers, since
any finalizers can end up queued together.

-}</span><span>
</span><span id="line-169"></span></pre></body></html>